import plotly.graph_objects as go
import networkx as nx
import numpy as np

# 模拟 45 部门的投入产出矩阵
num_sectors = 45
# 随机生成投入产出矩阵，这里只是示例，实际应使用真实数据
input_output_matrix = np.random.rand(num_sectors, num_sectors)

# 创建一个有向图对象
G = nx.DiGraph()

# 添加节点
for i in range(num_sectors):
    sector_name = f"部门 {i + 1}"
    G.add_node(sector_name)

# 添加边
for i in range(num_sectors):
    for j in range(num_sectors):
        if input_output_matrix[i][j] > 0:
            source = f"部门 {i + 1}"
            target = f"部门 {j + 1}"
            weight = input_output_matrix[i][j]
            G.add_edge(source, target, weight=weight)

# 计算节点的布局
pos = nx.spring_layout(G)

# 提取节点的坐标
node_x = []
node_y = []
node_text = []
for node in G.nodes():
    x, y = pos[node]
    node_x.append(x)
    node_y.append(y)
    node_text.append(node)

# 创建节点的散点图
node_trace = go.Scatter(
    x=node_x, y=node_y,
    mode='markers',
    hoverinfo='text',
    marker=dict(
        showscale=False,
        color='blue',
        size=10
    ),
    text=node_text
)

# 提取边的坐标和标签
edge_x = []
edge_y = []
edge_text = []
for edge in G.edges(data=True):
    x0, y0 = pos[edge[0]]
    x1, y1 = pos[edge[1]]
    edge_x.extend([x0, x1, None])
    edge_y.extend([y0, y1, None])
    edge_text.append(f"权重: {edge[2]['weight']:.2f}")

# 创建边的线图
edge_trace = go.Scatter(
    x=edge_x, y=edge_y,
    line=dict(width=0.5, color='#888'),
    hoverinfo='text',
    mode='lines',
    text=edge_text
)

# 创建图形对象
fig = go.Figure(data=[edge_trace, node_trace],
                layout=go.Layout(
                    title='45 部门投入产出图谱',
                    showlegend=False,
                    hovermode='closest',
                    margin=dict(b=20, l=5, r=5, t=40),
                    xaxis=dict(showgrid=False, zeroline=False, showticklabels=False),
                    yaxis=dict(showgrid=False, zeroline=False, showticklabels=False))
                )

# 显示图形
fig.show()